﻿//
// Copyright (c) 2011 David Díaz & Fran Pedreira
//
// This file is part of PlanSim.
//
// PlanSim is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PlanSim is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with PlanSim. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Drawing;

namespace PlanSim.Core
{
	public class Configuracion
	{
		public enum TipoCola { FCFS, SJF, RR, SRT };
		public enum EstrategiaPlanificador { MLQ, MLFQ }

		public class Dispositivo
		{
			/// <summary>
			/// Nombre del recurso
			/// </summary>
			public string Nombre
			{
				get { return nombre; }
				set { nombre = value; }
			}
			private string nombre;

			/// <summary>
			/// Estrategia a seguir por del recurso
			/// </summary>
			public TipoCola TipoCola
			{
				get { return tipoCola; }
				set { tipoCola = value; }
			}
			private TipoCola tipoCola;

			/// <summary>
			/// Valor del quantum (Para estrategia Round Robin)
			/// </summary>
			public int Quantum
			{
				get { return quantum; }
				set { quantum = value; }
			}
			private int quantum;

			/// <summary>
			/// Constructor por defecto. Para ser usado por el serializador.
			/// </summary>
			/// <remarks>
			/// No usar desde la aplicación. Desde la aplicación usar el constructor paramétrico.
			/// </remarks>
			public Dispositivo()
			{
			}

			/// <summary>
			/// Constructor Recurso.
			/// </summary>
			public Dispositivo(string nombre, TipoCola tipoCola, int quantum)
			{
				this.nombre = nombre;
				this.tipoCola = tipoCola;
				this.quantum = quantum;
			}
		}

		public class Cola
		{
			/// <summary>
			/// Nombre de la cola
			/// </summary>
			public string Nombre
			{
				get { return nombre; }
				set { nombre = value; }
			}
			private string nombre;

			// Prioridad de la cola.
			public int Prioridad
			{
				get { return prioridad; }
				set { prioridad = value; }
			}
			private int prioridad;

			/// <summary>
			/// Estrategia a seguir por la cola
			/// </summary>
			public TipoCola Tipo
			{
				get { return tipo; }
				set { tipo = value; }
			}
			private TipoCola tipo;

			/// <summary>
			/// Valor del quantum (Para estrategia Round Robin)
			/// </summary>
			public int Quantum
			{
				get { return quantum; }
				set { quantum = value; }
			}
			private int quantum;

			/// <summary>
			/// Constructor por defecto. Para ser usado por el serializador.
			/// </summary>
			/// <remarks>
			/// No usar desde la aplicación. Desde la aplicación usar el constructor paramétrico.
			/// </remarks>
			public Cola()
			{
			}

			/// <summary>
			/// Constructor Cola.
			/// </summary>
			public Cola(string nombre, int prioridad, TipoCola tipo, int quantum)
			{
				this.nombre = nombre;
				this.prioridad = prioridad;
				this.tipo = tipo;
				this.quantum = quantum;
			}
		}

		public class AccesoADispositivo
		{
			/// <summary>
			/// Identificación del acceso a dipositivo (por ejemplo: "imprimir documento" o "enviar paquete TCP")
			/// </summary>
			public string Nombre
			{
				get { return nombre; }
				set { nombre = value; }
			}
			private string nombre;

			/// <summary>
			/// Identificador del dispositivo al que se accede.
			/// </summary>
			public string Dispositivo
			{
				get { return dispositivo; }
				set { dispositivo = value; }
			}
			private string dispositivo;

			/// <summary>
			/// Nos indica si esta tarea se realiza de forma cíclica.
			/// </summary>
			public bool Ciclico
			{
				get { return ciclico; }
				set { ciclico = value; }
			}
			private bool ciclico;

			/// <summary>
			/// Cada cuanto se repite el uso del recurso.
			/// </summary>
			public int Periodo
			{
				get { return periodo; }
				set { periodo = value; }
			}
			private int periodo;

			/// <summary>
			/// Tiempo que conumira de recurso el proceso.
			/// </summary>
			public int Duracion
			{
				get { return duracion; }
				set { duracion = value; }
			}
			private int duracion;

			/// <summary>
			/// Constructor paramétrico.
			/// </summary>
			public AccesoADispositivo(string nombre, string dispositivo, bool ciclico, int periodo, int duracion)
			{
				this.nombre = nombre;
				this.dispositivo = dispositivo;
				this.ciclico = ciclico;
				this.periodo = periodo;
				this.duracion = duracion;
			}

			/// <summary>
			/// Constructor por defecto. No usar: es solo para que lo use el serializador Xml.
			/// </summary>
			public AccesoADispositivo()
			{
			}
		}

		public class Proceso
		{
			/// <summary>
			/// Nombre del proceso
			/// </summary>
			public string Nombre
			{
				get { return nombre; }
				set { nombre = value; }
			}
			private string nombre;

			/// <summary>
			/// Ciclo de de la simulación en el que entra el proceso.
			/// </summary>
			public int Entrada
			{
				get { return entrada; }
				set { entrada = value; }
			}
			private int entrada;

			/// <summary>
			/// Ciclos de CPU que dura el proceso.
			/// </summary>
			public int Duracion
			{
				get { return duracion; }
				set { duracion = value; }
			}
			private int duracion;

			/// <summary>
			/// Color para indentificar al proceso en el cronograma.
			/// </summary>
			public int Color
			{
				get { return color; }
				set { color = value; }
			}
			private int color;

			/// <summary>
			/// Nombre de la cola donde inicialmente se inicia un proceso.
			/// </summary>
			public string ColaInicial
			{
				get { return colaInicial; }
				set { colaInicial = value; }
			}
			private string colaInicial;

			/// <summary>
			/// Lista de Recursos con su información correspondiente
			/// </summary>
			public List<AccesoADispositivo> AccesosADispositivos = new List<AccesoADispositivo>();

			/// <summary>
			/// Constructor por defecto. Para ser usado por el serializador.
			/// </summary>
			/// <remarks>
			/// No usar desde la aplicación. Desde la aplicación usar el constructor paramétrico.
			/// </remarks>
			public Proceso()
			{
			}

			/// <summary>
			/// Constructor Proceso
			/// </summary>
			public Proceso(string nombre, int inicio, int duracion, string cola, int color)
			{
				this.nombre = nombre;
				this.entrada = inicio;
				this.duracion = duracion;
				this.colaInicial = cola;
				this.color = color;
			}
		}

        /// <summary>
        /// Identificador de la descripción.
        /// </summary>
        public string Nombre
        {
            get { return nombre; }
            set { nombre = value; }
        }
        private string nombre = "Sin nombre";

		/// <summary>
		/// Numero de procesadores empleados en la simulación
		/// </summary>
		public int NumeroProcesadores
		{
			get { return numeroProcesadores; }
			set { numeroProcesadores = value; }
		}
		private int numeroProcesadores;

		/// <summary>
		/// Tipo de estrategias que seguirá el planificador
		/// </summary>
		public EstrategiaPlanificador Estrategia
		{
			get { return estrategia; }
			set { estrategia = value; }
		}
		private EstrategiaPlanificador estrategia;

		/// <summary>
		/// Prioridad de acceso a las colas en la concurrencia al salir de recurso
		/// procesador o entrada de un nuevo proceso.
		/// 0: Nuevo, Saliendo de CPU, Saliendo de recurso
		/// 1: N,R,C
		/// 2: R,N,C
		/// 3: R,C,N
		/// 4: C,N,R
		/// 5: C,R,N
		/// </summary>
		public int PrioridadEnConcurrencia
		{
			get { return prioridadEnConcurrencia; }
			set { prioridadEnConcurrencia = value; }
		}
		private int prioridadEnConcurrencia;

		/// <summary>
		/// Lista de colas con su información correspondiente
		/// </summary>
		public List<Cola> Colas
		{
			get { return colas; }
			set { colas = value; }
		}
		private List<Cola> colas = new List<Cola>();

		/// <summary>
		/// Lista de Recursos con su información correspondiente
		/// </summary>
		public List<Dispositivo> Dispositivos
		{
			get { return dispositivos; }
			set { dispositivos = value; }
		}
		private List<Dispositivo> dispositivos = new List<Dispositivo>();

		/// <summary>
		/// Obtiene una referencia a la lista de procesos.
		/// </summary>
		public List<Proceso> Procesos
		{
			get { return procesos; }
			set { procesos = value; }
		}
		private List<Proceso> procesos = new List<Proceso>();

		/// <summary>
		/// Constructor Config.
		/// </summary>
		public Configuracion()
		{
		}

		public void GuardarEnFichero(string nombreFichero)
		{
			FileStream stream = new FileStream(nombreFichero, FileMode.Create);
			XmlSerializer serializador = new XmlSerializer(this.GetType());
			serializador.Serialize(stream, this);

            this.nombre = Path.GetFileName(nombreFichero);

			stream.Close();
		}

		public static Configuracion CargarDeFichero(string nombreFichero)
		{
			Configuracion configuracion = null;

			XmlSerializer serializador = new XmlSerializer(typeof(Configuracion));
			FileStream stream = new FileStream(nombreFichero, FileMode.Open);
			try 
			{	        
				configuracion = (Configuracion)serializador.Deserialize(stream);
			}
			catch (Exception) {}
			stream.Close();

            if (configuracion != null)
                configuracion.nombre = Path.GetFileName(nombreFichero);

			return configuracion;
		}
	}
}
